home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 4 / United Public Domain Gold 4.iso / fredfish / ff.0014.dms / ff.0014.adf / dex / dex0.c < prev    next >
C/C++ Source or Header  |  1990-04-10  |  24KB  |  1,165 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *            Copyright (c) 1982, Fred Fish            *
  4.  *                All Rights Reserved                *
  5.  *                                    *
  6.  *    This software and/or documentation is released for public    *
  7.  *    distribution for personal, non-commercial use only.        *
  8.  *    Limited rights to use, modify, and redistribute are hereby    *
  9.  *    granted for non-commercial purposes, provided that all        *
  10.  *    copyright notices remain intact and all changes are clearly    *
  11.  *    documented.  The author makes no warranty of any kind with    *
  12.  *    respect to this product and explicitly disclaims any implied    *
  13.  *    warranties of merchantability or fitness for any particular    *
  14.  *    purpose.                            *
  15.  *                                    *
  16.  ************************************************************************
  17.  */
  18.  
  19.  
  20. /*
  21.  *  FILE
  22.  *
  23.  *    dex0.c   main routines for documentation extraction utility
  24.  *
  25.  *  DESCRIPTION
  26.  *
  27.  *    Contains the main routines and misc utility routines for dex.
  28.  *
  29.  *  FUNCTIONS
  30.  *
  31.  *    main           entry point for dex utility
  32.  *    tolower        convert alpha characters to lower case
  33.  *    options        process options list on cmd line
  34.  *    usage          give usage message and abort
  35.  *    indentation    set indentation level
  36.  *    nofill         turn off fill mode
  37.  *    fill           turn on fill mode
  38.  *    asterisks      form box top or bottom
  39.  *    emit_bline     emit cmds for blank line
  40.  *    set_section    lookup and set current section
  41.  *    reset_section  reset current section (no section)
  42.  *    emit_filled    emit text in filled mode
  43.  *    emit_unfilled  emit text in unfilled mode
  44.  *    set_output     switch output stream
  45.  *
  46.  *  AUTHOR
  47.  *
  48.  *    Fred Fish
  49.  *
  50.  */
  51.  
  52. /*
  53.  *  TOOL
  54.  *
  55.  *    dex   documentation extraction utility
  56.  *
  57.  *  SYNOPSIS
  58.  *
  59.  *    dex [-dhtv] [-r rcfile] file1 file2 file3 ...
  60.  *
  61.  *        d =>  enable debug mode
  62.  *        h =>  print internal help message
  63.  *        t =>  enable trace mode
  64.  *        v =>  enable verbose mode
  65.  *
  66.  *        r =>  use reconfiguration file <rcfile>
  67.  *
  68.  *  DESCRIPTION
  69.  *
  70.  *    Dex extracts internal documentation from program source
  71.  *    files, compiling it into a form suitable for input
  72.  *    to the nroff text formatter.  It was developed primarily
  73.  *    to aid the author in maintaining "up to date" documentation
  74.  *    for each function in the portable math library (PML).
  75.  *
  76.  *    For further information consult the document
  77.  *    "DEX - Documentation Extraction Utility".
  78.  *
  79.  *  EXAMPLE
  80.  *
  81.  *    The output of dex is typically collected in one
  82.  *    or more files to be inserted in the appropriate
  83.  *    places in other "skeleton" files during nroff
  84.  *    processing.
  85.  *
  86.  *    For example, in the portable math library usage,
  87.  *    the following sequence of commands will rebuild
  88.  *    the library documentation to reflect the current
  89.  *    state of the library.
  90.  *
  91.  *       cd /usr/public/pml
  92.  *       dex *
  93.  *       nroff -mm pml.r >pml.doc
  94.  *
  95.  *    The command "dex *" extracts function and file documentation
  96.  *    from all the files in the library, and builds two output
  97.  *    files, "funcs.r" and "files.r".   The "funcs.r" file
  98.  *    contains documentation on each of the library functions.
  99.  *    The "files.r" file contains documentation on each of the
  100.  *    files in the portable math library directory.  The "pml.r"
  101.  *    file is an nroff file containing information common
  102.  *    to all files and functions.  At the points where the
  103.  *    "funcs.r" and "files.r" files are to be inserted, there
  104.  *    is a ".so <filename>" nroff command.
  105.  *
  106.  */
  107.  
  108. /*
  109.  *  FILES
  110.  *
  111.  *    ".dexrc"   dex reconfiguration file [default]
  112.  *
  113.  *  BUGS
  114.  *
  115.  *    Items are currently collected as encountered in the files
  116.  *    specified in the command line.  A planned future enhancement
  117.  *    is to sort the collected documentation regions by name.
  118.  *
  119.  *    Lines which being with a "." character, such as the
  120.  *    line in the "FILES" section above, cause nroff to
  121.  *    occasionally do unintended things.
  122.  *
  123.  *    The dynamic reconfiguration capability is relatively
  124.  *    primitive.  Once the requirements are more clear,
  125.  *    a future version will be more flexible.
  126.  *
  127.  *  AUTHOR
  128.  *
  129.  *    Fred Fish
  130.  *
  131.  */
  132.  
  133. #include <stdio.h>
  134. #include "hashtbl.h"
  135. #include "dex.h"
  136.  
  137. /*
  138.  *    Some misc global variables.
  139.  */
  140.  
  141. struct tbl_data *section=NULL;    /* Current section being processed */
  142. char *infile = "stdin";        /* Input file name if not stdin */
  143. char *rcfile = ".dexrc";    /* Reconfiguration file */
  144. int filled = TRUE;        /* Flag for fill mode on */
  145. int trace = FALSE;        /* Trace flag */
  146. int vflag = FALSE;        /* Verbose flag */
  147. int debug = FALSE;        /* Debug flag */
  148. extern int yydebug;        /* YACC internal debug flag */
  149. int indent_level = 0;        /* Current indentation level */
  150. int linenum = 1;        /* Current input file line number */
  151. FILE *infp = stdin;        /* Lexical analysis input stream */
  152. FILE *fp = stdout;        /* Current output stream */
  153. char title[128];        /* Title of current region */
  154.  
  155. /*
  156.  *    Some misc local variables.
  157.  */
  158.  
  159. static int suppress = FALSE;    /* Flag for region suppression */
  160. static int box_emitted = FALSE;    /* Flag for box has been emitted for region */
  161.  
  162.  
  163. /*
  164.  *    The following documentation will be printed out when DEX is
  165.  *    invoked with the -h argument.
  166.  */
  167.  
  168. static char *documentation[] = {
  169.     "",
  170.     "DESCRIPTION",
  171.     "",
  172.     "\tDex is a program for extracting documentation from program",
  173.     "\tsource files, building files suitable for input to a",
  174.     "\ttext formatter (such as nroff).",
  175.     "",
  176.     "USAGE",
  177.     "",
  178.     "\tdex [-dhtv] [-f rcfile] file1 file2 ...",
  179.     "",
  180.     "\t\t-d    enable debug output (implies -v)",
  181.     "\t\t-h    print this help info",
  182.     "\t\t-t    enable trace output",
  183.     "\t\t-v    verbose mode",
  184.     "",
  185.     "\t\t-f    use specified reconfiguration file",
  186.     "\t\t      (default \".dexrc\")",
  187.     "",
  188.     "OUTPUTS",
  189.     "",
  190.     "\tBy default DEX writes all output to stdout.",
  191.     "\tThis can be changed via the reconfiguration file.",
  192.     "",
  193.     0
  194. };
  195.  
  196.  
  197. /*
  198.  *  FUNCTION
  199.  *
  200.  *    main   DEX entry point
  201.  *
  202.  *  KEY WORDS
  203.  *
  204.  *    dex entry point
  205.  *    main
  206.  *
  207.  *  SYNOPSIS
  208.  *
  209.  *    main(argc,argv)
  210.  *    int argc;
  211.  *    char *argv[];
  212.  *
  213.  *  DESCRIPTION
  214.  *
  215.  *    This is where DEX starts executing.  All argument list
  216.  *    switches are processed first, then all the specified
  217.  *    files are processed.
  218.  *
  219.  */
  220.  
  221. /*
  222.  *  PSEUDO CODE
  223.  *
  224.  *    Begin main
  225.  *        Process command line options.
  226.  *        For each argument list field
  227.  *        If field was not erased during option processing
  228.  *            If there is a previously processed file open
  229.  *            Close the previous file.
  230.  *            End if
  231.  *            If the current file cannot be opened then
  232.  *            Print error message.
  233.  *            Else
  234.  *            Save input file name for future use.
  235.  *            Reset current line number to 1.
  236.  *            Do any reconfiguration requested.
  237.  *            If verbose then tell user file name.
  238.  *            Process the input file.
  239.  *            Close the input file.
  240.  *            End if
  241.  *        End if
  242.  *        End for
  243.  *        Exit with "normal" status.
  244.  *    End main
  245.  *
  246.  */
  247.  
  248. main(argc, argv)
  249. int argc;
  250. char *argv[];
  251. {
  252.     FILE *fopen();
  253.     char *argp;
  254.     int argnum;
  255.  
  256.     options(argc,argv);
  257.     for (argnum = 1; argnum < argc; argnum++) {
  258.         if ((argp = argv[argnum]) != NULL) {
  259.             if (infp != NULL) {
  260.             fclose(infp);
  261.         }
  262.             if ((infp = fopen(argp,"r")) == NULL) {
  263.         perror(argp);
  264.         } else {
  265.             infile = argp;
  266.             linenum = 1;
  267.         reconfig(argp,rcfile);
  268.         if (debug) {dump_tbl();}
  269.         if (vflag) {printf("dex: processing \"%s\"\n",argp);}
  270.             yyparse();
  271.         fclose(infp);
  272.             }
  273.         }
  274.     }
  275.     if (infp == stdin) {
  276.     linenum = 1;
  277.     reconfig(".",rcfile);
  278.     yyparse();
  279.     }
  280.     exit(NORMAL_EXIT);
  281. }
  282.  
  283. /*
  284.  *  FUNCTION
  285.  *
  286.  *    tolower   force alphabetic characters to lower case
  287.  *
  288.  *  SYNOPSIS
  289.  *
  290.  *    char tolower(ch)
  291.  *    char ch;
  292.  *
  293.  *  DESCRIPTION
  294.  *
  295.  *    Tolower forces alphabetic upper case characters to lower case.
  296.  *    If the input character is already lower case, or is not
  297.  *    alphabetic, then it is simply returned unchanged.
  298.  *
  299.  *  BUGS
  300.  *
  301.  *    Currently works only if native character set is ASCII.
  302.  *
  303.  */
  304.  
  305. /*
  306.  *  PSEUDO CODE
  307.  *
  308.  *    Begin tolower
  309.  *        If character is an upper case alphabetic then
  310.  *        Convert character to lower case and return it.
  311.  *        Else
  312.  *        Return character unchanged.
  313.  *        End if
  314.  *    End tolower
  315.  *
  316.  */
  317.  
  318. #ifndef tolower
  319. char tolower(ch)
  320. char ch;
  321. {
  322.     if ('A' <= ch && ch <= 'Z') {
  323.     return(ch + 040);
  324.     } else {
  325.     return(ch);
  326.     }
  327. }
  328. #endif
  329.  
  330. /*
  331.  *  FUNCTION
  332.  *
  333.  *    options   process command line options
  334.  *
  335.  *  SYNOPSIS
  336.  *
  337.  *    options(argc,argv)
  338.  *    int argc;
  339.  *    char *argv[];
  340.  *
  341.  *  DESCRIPTION
  342.  *
  343.  *    Scans argument list, processing each switch as it is
  344.  *    found.  The pointer to each switch string is then
  345.  *    replaced with a NULL to effectively erase the switch
  346.  *    argument.
  347.  *
  348.  */
  349.  
  350. /*
  351.  *  PSEUDO CODE
  352.  *
  353.  *    Begin options
  354.  *        For each argument in the argument list
  355.  *        Get pointer to first char of argument.
  356.  *        If the argument is a switch then
  357.  *            Replace argument pointer with NULL.
  358.  *            Look at next argument character.
  359.  *            While there is another argument character
  360.  *            Switch on the argument character
  361.  *            Case "verbose":
  362.  *                Set verbose flag.
  363.  *                Break out of switch.
  364.  *            Case "debug":
  365.  *                Set debug flag.
  366.  *                Set YACC debug flag.
  367.  *                Break out of switch.
  368.  *            Case "reconfigure":
  369.  *                If reconfig file is next arg
  370.  *                If there is no next arg
  371.  *                    Abort with usage message.
  372.  *                Else 
  373.  *                    Save file name.
  374.  *                    If file is actually switch
  375.  *                        Abort with usage message.
  376.  *                    Else
  377.  *                        Erase reconfig switch
  378.  *                    End if
  379.  *                End if
  380.  *                Else
  381.  *                Save pntr to reconfig filename.
  382.  *                End if
  383.  *                Break out of switch.
  384.  *            Case "trace":
  385.  *                Set trace flag.
  386.  *                Break out of switch.
  387.  *            Default:
  388.  *                Abort with usage message.
  389.  *            End switch
  390.  *            End while
  391.  *        End if
  392.  *        End for
  393.  *    End options
  394.  *
  395.  */
  396.  
  397. options(argc, argv)
  398. int argc;
  399. char *argv[];
  400. {
  401.     int i;
  402.     char c;        /* 1st char of current command-line argument */
  403.     char *cp;        /* current argument pointer */
  404.  
  405.     for (i=1; i<argc; i++) {
  406.         cp = argv[i];
  407.         if (*cp == '-') {
  408.             argv[i] = NULL;
  409.         cp++;
  410.         while (c = *cp++) {
  411.             switch (tolower(c)) {
  412.             case 'v':
  413.                 vflag++;
  414.                 break;
  415.             case 'd':
  416.                 debug++;
  417.             yydebug++;
  418.             vflag++;
  419.                 break;
  420.             case 'f':
  421.                 if (*cp == NULL) {
  422.                 if (++i >= argc) {
  423.                     usage(c);
  424.             } else {
  425.                 rcfile = argv[i];
  426.                 if (*rcfile == '-') {
  427.                          usage(c);
  428.                 } else {
  429.                       argv[i] = NULL;
  430.                 }
  431.                    }
  432.                 } else {
  433.               rcfile = cp;
  434.                 }
  435.                 break;
  436.         case 't':
  437.             trace++;
  438.             break;
  439.             default:
  440.                 usage(c);
  441.             }
  442.             }
  443.         }
  444.     }
  445. }
  446.  
  447. /*
  448.  *  FUNCTION
  449.  *
  450.  *    usage   give usage message and abort
  451.  *
  452.  *  KEY WORDS
  453.  *
  454.  *    usage
  455.  *    help processing
  456.  *    abort locations
  457.  *
  458.  *  SYNOPSIS
  459.  *
  460.  *    usage(ch)
  461.  *    char ch;       (is h for explicit help)
  462.  *
  463.  *  DESCRIPTION
  464.  *
  465.  *    Usage is typically called when a problem has been
  466.  *    detected in the argument list, or usage help has
  467.  *    been explicitly requested (via the -h flag).
  468.  *    It prints an appropriate usage message and then aborts.
  469.  *
  470.  */
  471.  
  472. /*
  473.  *  PSEUDO CODE
  474.  *
  475.  *    Begin usage
  476.  *        If character is not the explicit help character then
  477.  *        Print a brief usage message.
  478.  *        Print how to get more help.
  479.  *        Else
  480.  *        Initialize internal documentation pointer.
  481.  *        While there is a line of documentation to print
  482.  *            Print the line of documentation.
  483.  *        End while
  484.  *        End if
  485.  *        Exit with error status.
  486.  *    End usage
  487.  *
  488.  */
  489.  
  490. usage(c)
  491. char c;        /* The char of the option */
  492. {
  493.     register char **dp;
  494.  
  495.     if (c != 'h') {
  496.         printf("Usage: dex [-dhv] [-f rcfile]\n");
  497.     printf("       dex -h for help.\n");
  498.     } else {
  499.     dp = documentation;
  500.     while (*dp != NULL) {
  501.         printf("%s\n",*dp++);
  502.     }
  503.     }
  504.     exit(ERROR_EXIT);
  505. }
  506.  
  507. /*
  508.  *  FUNCTION
  509.  *
  510.  *    indentation   set indentation to specified level
  511.  *
  512.  *  KEY WORDS
  513.  *
  514.  *    indent level
  515.  *    emit functions
  516.  *
  517.  *  SYNOPSIS
  518.  *
  519.  *    indentation(where)
  520.  *    int where;
  521.  *
  522.  *  DESCRIPTION
  523.  *
  524.  *    Checks requested indentation level against current
  525.  *    indentation level.  If they do not match then
  526.  *    emits appropriate nroff command to set indentation
  527.  *    to the specified level.
  528.  *
  529.  */
  530.  
  531. /*
  532.  *  PSEUDO CODE
  533.  *
  534.  *    Begin indentation
  535.  *        If current level is not that requested then
  536.  *        Emit command to change indentation.
  537.  *        Update the current indentation level.
  538.  *        End if
  539.  *    End indentation
  540.  *
  541.  */
  542.  
  543. indentation(where)
  544. int where;
  545. {
  546.     char buffer[16];
  547.  
  548.     if (indent_level != where) {
  549.     sprintf(buffer,".in %d",where);
  550.     emit(buffer,NULL);
  551.     indent_level = where;
  552.     }
  553. }
  554.  
  555. /*
  556.  *  FUNCTION
  557.  *
  558.  *    nofill   if filled mode is on, turn it off
  559.  *
  560.  *  KEY WORDS
  561.  *
  562.  *    fill mode
  563.  *    emit functions
  564.  *
  565.  *  SYNOPSIS
  566.  *
  567.  *    nofill()
  568.  *
  569.  *  DESCRIPTION
  570.  *
  571.  *    Forces fill mode to be off.  If fill mode is currently
  572.  *    on then emits suitable command to turn it off.
  573.  *
  574.  */
  575.  
  576. /*
  577.  *  PSEUDO CODE
  578.  *
  579.  *    Begin nofill
  580.  *        If filled mode is on then
  581.  *        Emit command to turn it off.
  582.  *        Remember that it is now off.
  583.  *        End if
  584.  *    End nofill
  585.  *
  586.  */
  587.  
  588. nofill()
  589. {
  590.     if (filled) {
  591.         emit(".nf",NULL);
  592.         filled = FALSE;
  593.     }
  594. }
  595.  
  596. /*
  597.  *  FUNCTION
  598.  *
  599.  *    fill   if fill mode is off, turn it on
  600.  *
  601.  *  KEY WORDS
  602.  *
  603.  *    fill mode
  604.  *    emit functions
  605.  *
  606.  *  SYNOPSIS
  607.  *
  608.  *    fill()
  609.  *
  610.  *  DESCRIPTION
  611.  *
  612.  *    Forces fill mode to be on.  If fill mode is currently
  613.  *    off then emits suitable command to turn it on.
  614.  *
  615.  */
  616.  
  617. /*
  618.  *  PSEUDO CODE
  619.  *
  620.  *    Begin fill
  621.  *        If filled mode is off then
  622.  *        Emit command to turn it on.
  623.  *        Remember that it is now on.
  624.  *        End if
  625.  *    End fill
  626.  *
  627.  */
  628.  
  629. fill()
  630. {
  631.     if (!filled) {
  632.         emit(".fi",NULL);
  633.         filled = TRUE;
  634.     }
  635. }
  636.  
  637. /*
  638.  *  FUNCTION
  639.  *
  640.  *    asterisks   emit command for centered asterisks line
  641.  *
  642.  *  KEY WORDS
  643.  *
  644.  *    emit functions
  645.  *    box construction
  646.  *
  647.  *  SYNOPSIS
  648.  *
  649.  *    asterisks(how_many)
  650.  *    int how_many;
  651.  *
  652.  *  DESCRIPTION
  653.  *
  654.  *    Emits a command to center a line with the specified
  655.  *    number of asterisks.  This is used to form the top
  656.  *    and bottom of a boxed item in the output.
  657.  *
  658.  */
  659.  
  660. /*
  661.  *  PSEUDO CODE
  662.  *
  663.  *    Begin asterisks
  664.  *        For the specified number of asterisks
  665.  *        Accumulate asterisk in buffer.
  666.  *        End for
  667.  *        Null terminate buffer string.
  668.  *        Emit command to cause line to be centered.
  669.  *        Emit asterisks buffer.
  670.  *    End asterisks
  671.  *
  672.  */
  673.  
  674. asterisks(how_many)
  675. int how_many;
  676. {
  677.     int count;
  678.     char buffer[128];
  679.     char *bp;
  680.  
  681.     for (bp = buffer, count = 0 ; count < how_many; count++) {
  682.     *bp++ = '*';
  683.     }
  684.     *bp = NULL;
  685.     emit(".ce",NULL);
  686.     emit(buffer,'\\');
  687. }
  688.  
  689. /*
  690.  *  FUNCTION
  691.  *
  692.  *    emit_bline   emit command to form blank line
  693.  *
  694.  *  KEY WORDS
  695.  *
  696.  *    blank line
  697.  *    emit functions
  698.  *
  699.  *  SYNOPSIS
  700.  *
  701.  *    emit_bline()
  702.  *
  703.  *  DESCRIPTION
  704.  *
  705.  *    Emits a suitable command to form a blank line in the
  706.  *    output.  Checks first to verify that output is not
  707.  *    being suppressed and the the current section is
  708.  *    enabled for processing.  Finally, the current section
  709.  *    must be enabled for text emission.
  710.  *
  711.  */
  712.  
  713. /*
  714.  *  PSEUDO CODE
  715.  *
  716.  *    Begin emit_bline
  717.  *        If there is a current section being processed then
  718.  *        If output is not suppressed and processing is enabled
  719.  *            If the section is enabled for text emission then
  720.  *            Emit command to form blank line.
  721.  *            End if
  722.  *        End if
  723.  *        End if
  724.  *    End emit_bline
  725.  *
  726.  */
  727.  
  728. emit_bline ()
  729. {
  730.     if (section != NULL) {
  731.     if (!suppress && (section->flags & PROCESS)) {
  732.         if (section->flags & EMITTEXT) {
  733.         emit(".sp 1",NULL);
  734.         }
  735.     }
  736.     }
  737. }
  738.  
  739. /*
  740.  *  FUNCTION
  741.  *
  742.  *    set_section   lookup and set current section
  743.  *
  744.  *  KEY WORDS
  745.  *
  746.  *    emit functions
  747.  *    section selection
  748.  *    region suppression
  749.  *
  750.  *  SYNOPSIS
  751.  *
  752.  *    set_section(name)
  753.  *    char *name;
  754.  *
  755.  *  DESCRIPTION
  756.  *
  757.  *    Looks up the specified section and makes it the
  758.  *    current section.   Resets the region
  759.  *    "box-emitted" and "suppress processing" flags.
  760.  *    Also sets the indentation level back to the left
  761.  *    margin and emits commands to print the section
  762.  *    name (underlined).
  763.  *
  764.  */
  765.  
  766. /*
  767.  *  PSEUDO CODE
  768.  *
  769.  *    Begin set_section
  770.  *        Reset the box emitted flag for region.
  771.  *        Lookup the section and make it current.
  772.  *        If section name was found in table then
  773.  *        If the section begins a region then
  774.  *            If the section is to be processed
  775.  *            The region is processed also.
  776.  *            Switch output stream.
  777.  *            Emit cmd for indentation.
  778.  *            Set indentation to zero.
  779.  *            Emit cmd for filled mode.
  780.  *            Set filled mode.
  781.  *            Else
  782.  *            The region is suppressed.
  783.  *            End if
  784.  *        End if
  785.  *        If not suppressed and can be processed
  786.  *            Set indentation level back.
  787.  *            If new page is desired then
  788.  *            Emit command to start new page.
  789.  *            End if
  790.  *            If text emission is enabled then
  791.  *            If name is to be underlined
  792.  *                Emit underline command.
  793.  *            End if
  794.  *            Emit section name.
  795.  *            End if
  796.  *        End if
  797.  *        End if
  798.  *    End set_section
  799.  *
  800.  */
  801.  
  802. set_section(name)
  803. char *name;
  804. {
  805.     struct tbl_data *tbl_find();
  806.  
  807.     box_emitted = FALSE;
  808.     if (debug) {printf("set_section: looking for \"%s\"\n",name);}
  809.     section = tbl_find(name);
  810.     if (section != NULL) {
  811.     if (section->flags & REGION) {
  812.         if (debug) {printf("set_section: REGION flag set\n");}
  813.         if (section->flags & PROCESS) {
  814.             if (debug) {printf("set_section: PROCESS flag set\n");}
  815.         suppress = FALSE;
  816.         set_output(section);
  817.         emit(".in 0",NULL);
  818.         indent_level = 0;
  819.         emit(".fi",NULL);
  820.         filled = TRUE;
  821.         } else {
  822.         suppress = TRUE;
  823.         }
  824.     }
  825.     if (!suppress && (section->flags & PROCESS)) {
  826.         if (debug) {printf("set_section: PROCESS flag set\n");}
  827.         indentation(0);
  828.         if (section->flags & EMITBP) {
  829.         emit(".bp",NULL);
  830.         }
  831.         if (section->flags & EMITTEXT) {
  832.             if (debug) {printf("set_section: EMITTEXT flag set\n");}
  833.         if (section->flags & EMITUL) {
  834.             emit(".ul 1",NULL);
  835.         }
  836.         emit(name,'\\');
  837.         }
  838.     }
  839.     }
  840. }
  841.  
  842. /*
  843.  *  FUNCTION
  844.  *
  845.  *    reset_section   reset current section
  846.  *
  847.  *  KEY WORDS
  848.  *
  849.  *    sections
  850.  *
  851.  *  SYNOPSIS
  852.  *
  853.  *    reset_section();
  854.  *
  855.  *  DESCRIPTION
  856.  *
  857.  *    Resets current section so that there is no section selected.
  858.  *    This is usually used when a non documentation line
  859.  *    (I.E code) is encountered.  It terminates processing of the
  860.  *    current section.
  861.  *
  862.  */
  863.  
  864. /*
  865.  *  PSEUDO CODE
  866.  *
  867.  *    Begin reset_section
  868.  *        Set current section to NULL.
  869.  *    End reset section
  870.  *
  871.  */
  872.  
  873. reset_section()
  874. {
  875.     section = NULL;
  876. }
  877.  
  878. /*
  879.  *  FUNCTION
  880.  *
  881.  *    emit_filled   emit text in filled mode
  882.  *
  883.  *  KEY WORDS
  884.  *
  885.  *    emit functions
  886.  *    text emission
  887.  *
  888.  *  SYNOPSIS
  889.  *
  890.  *    emit_filled(text)
  891.  *    char *text;
  892.  *
  893.  *  DESCRIPTION
  894.  *
  895.  *    Attempts to emit text in filled mode.  If filled
  896.  *    mode is not enabled for the section then emits
  897.  *    the text in unfilled mode.   Also attempts
  898.  *    to print the first field of the text in a box,
  899.  *    if the box output is enabled and has not yet been
  900.  *    emitted for the current documentation section.
  901.  *
  902.  */
  903.  
  904. /*
  905.  *  PSEUDO CODE
  906.  *
  907.  *    Begin emit_filled
  908.  *        If there is a current section then
  909.  *        If section is not suppressed and can be processed
  910.  *            If box emission is enabled for section
  911.  *            If box has not yet been emitted then
  912.  *                Get string to box.
  913.  *                Emit command for blank lines.
  914.  *                Emit commands for box top.
  915.  *                Emit commands to center string.
  916.  *                Emit commands for box bottom.
  917.  *                Emit commands for blank lines.
  918.  *                Set the box emitted flag.
  919.  *            End if
  920.  *            End if
  921.  *            If text emission is enabled then
  922.  *            Set indentation level.
  923.  *            If section is enabled for fill then
  924.  *                Emit commands for fill.
  925.  *            Else
  926.  *                Emit commands for no fill.
  927.  *            End if
  928.  *            Emit the text.
  929.  *            End if
  930.  *        End if
  931.  *        End if
  932.  *    End emit_filled
  933.  *
  934.  */
  935.  
  936. emit_filled(text)
  937. char *text;
  938. {
  939.     char buffer[128];
  940.  
  941.     if (section != NULL) {
  942.     if (!suppress && (section->flags & PROCESS)) {
  943.         if (section->flags & EMITBOX) {
  944.         if (!box_emitted) {
  945.             xfield(title,text);
  946.             emit(".sp 3",NULL);
  947.             asterisks(strlen(title)+4);
  948.             emit(".ce",NULL);
  949.             sprintf(buffer,"* %s *",title);
  950.             emit(buffer,'\\');
  951.             asterisks(strlen(title)+4);
  952.             emit(".sp 3",NULL);
  953.             box_emitted = TRUE;
  954.         }
  955.         }
  956.         if (section->flags & EMITTEXT) {
  957.         indentation(8);
  958.         if (section->flags & EMITFILL) {
  959.             fill();
  960.         } else {
  961.             nofill();
  962.         }
  963.         emit(text,'\\');
  964.         }
  965.     }
  966.     }
  967. }
  968.  
  969. /*
  970.  *  FUNCTION
  971.  *
  972.  *    emit_unfilled   emit text in unfilled mode
  973.  *
  974.  *  KEY WORDS
  975.  *
  976.  *    text emission
  977.  *    emit functions
  978.  *
  979.  *  SYNOPSIS
  980.  *
  981.  *    emit_unfilled(text)
  982.  *    char *text;
  983.  *
  984.  *  DESCRIPTION
  985.  *
  986.  *    Emits text in unfilled mode providing there is
  987.  *    a current section, it is not being suppressed,
  988.  *    and it is enabled for processing and text emission.
  989.  *
  990.  */
  991.  
  992. /*
  993.  *  PSEUDO CODE
  994.  *
  995.  *    Begin emit_unfilled
  996.  *        If there is a current section then
  997.  *        If section is not suppressed and can be processed
  998.  *            If section is enabled for text emission
  999.  *            Set nofill mode.
  1000.  *            Set indentation level.
  1001.  *            Emit text.
  1002.  *            End if
  1003.  *        End if
  1004.  *        End if
  1005.  *    End emit_unfilled
  1006.  *
  1007.  */
  1008.  
  1009. emit_unfilled(text)
  1010. char *text;
  1011. {
  1012.     if (section != NULL) {
  1013.     if (!suppress && (section->flags & PROCESS)) {
  1014.         if (section->flags & EMITTEXT) {
  1015.         nofill();
  1016.         indentation(16);
  1017.         emit(text,'\\');
  1018.         }
  1019.     }
  1020.     }
  1021. }
  1022.  
  1023. /*
  1024.  *  FUNCTION
  1025.  *
  1026.  *    set_output   switch output stream
  1027.  *
  1028.  *  KEY WORDS
  1029.  *
  1030.  *    output switching
  1031.  *
  1032.  *  SYNOPSIS
  1033.  *
  1034.  *    set_output(region)
  1035.  *    struct tbl_data *region;
  1036.  *
  1037.  *  DESCRIPTION
  1038.  *
  1039.  *    Tests to see if the region output has been redirected
  1040.  *    to a file.  If so, opens the file if necessary and
  1041.  *    remembers the file pointer in the table entry structure.
  1042.  *
  1043.  *    If no file is specified then the output goes to the
  1044.  *    standard output.
  1045.  *
  1046.  *    Initializes the global output pointer to point to
  1047.  *    the stream where output goes.
  1048.  *
  1049.  */
  1050.  
  1051. /*
  1052.  *  PSEUDO CODE
  1053.  *
  1054.  *    Begin set_output
  1055.  *        If the table entry pointer is valid then
  1056.  *            If the region has no output file
  1057.  *            Direct output to standard out.
  1058.  *        Else
  1059.  *            If the file is open then
  1060.  *            Set output to go to file.
  1061.  *            Else
  1062.  *                If file open succeeds
  1063.  *                Remember file pointer.
  1064.  *            Else
  1065.  *                Set output to stdout.
  1066.  *                End if
  1067.  *            End if
  1068.  *            End if
  1069.  *        End if
  1070.  *    End set_output
  1071.  *
  1072.  */
  1073.  
  1074. set_output(region)
  1075. struct tbl_data *region;
  1076. {
  1077.     if (region != NULL) {
  1078.     if (region->out == NULL) {
  1079.         fp = stdout;
  1080.     } else {
  1081.         if (region->ofp != NULL) {
  1082.         fp = region->ofp;
  1083.         } else {
  1084.         if ((fp = fopen(region->out,"w")) != NULL) {
  1085.             region->ofp = fp;
  1086.         } else {
  1087.             fp = stdout;
  1088.         }
  1089.         }
  1090.     }
  1091.     }
  1092. }
  1093.  
  1094. /*
  1095.  *  FUNCTION
  1096.  *
  1097.  *    emit   do actual output to current output stream
  1098.  *
  1099.  *  KEY WORDS
  1100.  *
  1101.  *    I/O functions
  1102.  *    emit
  1103.  *
  1104.  *  SYNOPSIS
  1105.  *
  1106.  *    emit(text,quote)
  1107.  *    char *text;
  1108.  *    char quote;
  1109.  *
  1110.  *  DESCRIPTION
  1111.  *
  1112.  *    Calls appropriate operating system and/or library
  1113.  *    functions to do the actual I/O.  Is localized here
  1114.  *    for both logical and portability reasons.
  1115.  *
  1116.  *    Emit will automatically append a newline to the output
  1117.  *    of each string.  Also, if the quote character is not
  1118.  *    null then all '\' and '.' characters will be preceeded by a
  1119.  *    '\' character.
  1120.  *
  1121.  */
  1122.  
  1123. /*
  1124.  *  PSEUDO CODE
  1125.  *
  1126.  *    Begin emit
  1127.  *        If text pointer is not invalid pointer then
  1128.  *        While there is another character to emit
  1129.  *            If quote flag set and char needs quoting
  1130.  *            Emit quote character.
  1131.  *            End if
  1132.  *            Emit character.
  1133.  *        End while
  1134.  *        Emit newline character.
  1135.  *        End if
  1136.  *    End emit
  1137.  *
  1138.  */
  1139.  
  1140. emit(text,quote)
  1141. char *text;
  1142. char quote;
  1143. {
  1144.     if (text != NULL) {
  1145.     while (*text != NULL) {
  1146.         if (quote != NULL && (*text == '.' || *text == '\\')) {
  1147.         fputc(quote,fp);
  1148.         }
  1149.         fputc(*text++,fp);
  1150.     }
  1151.     fputc('\n',fp);
  1152.     }
  1153. }
  1154.  
  1155. #ifndef unix
  1156. perror (err)
  1157. char *err;
  1158. {
  1159.     if (err && *err) {
  1160.         fprintf (stderr, "%s: ", err);
  1161.     }
  1162.     fprintf (stderr, "<unknown error!>\n");
  1163. }
  1164. #endif unix
  1165.